unit wvSQLite;

{$WARN SYMBOL_PLATFORM OFF}

interface

uses
  ComObj, ActiveX, wvSQLite3_TLB, StdVcl, Data.DB, Data.SqlExpr, Data.DbxSqlite,
  System.SysUtils, System.Classes, Data.DBXCommon;

type
  TSQLite = class(TAutoObject, ISQLite)
  strict private
    FConnection: TSQLConnection;
    FSQLQuery: TSQLQuery;
    FTransaction: TDBXTransaction;

  protected
    function InTransaction: Integer; safecall;
    procedure BeginTransaction; safecall;
    procedure CommitTransaction; safecall;
    procedure RollbackTransaction; safecall;

    procedure QueryAdd(const Value: WideString); safecall;
    procedure QueryClear; safecall;

    procedure Database(const DatabaseName: WideString; FailIfMissing: Integer); safecall;
    function Connect: Integer; safecall;
    function Connected: Integer; safecall;
    procedure Disconnect; safecall;

    function ExecuteSQL(const SQL: WideString): Integer; safecall;
    function ExecuteQuery: Integer; safecall;

    procedure OpenQuery; safecall;
    procedure OpenSQL(const SQL: WideString); safecall;

    function TableExists(const Index: WideString): Integer; safecall;
    function FieldName(Index: Integer): WideString; safecall;
    function FieldsCount: Integer; safecall;

    function ValueByName(const Index: WideString): OleVariant; safecall;
    function ValueByIndex(Index: Integer): OleVariant; safecall;

    function Bof: Integer; safecall;
    function Eof: Integer; safecall;
    function RecordCount: Integer; safecall;
    function GetRecNo: Integer; safecall;
    procedure SetRecNo(Index: Integer); safecall;

    function Next: Integer; safecall;
    procedure First; safecall;
    procedure Last; safecall;
    function RecCnt(Ina: Integer): Integer; safecall;
  public
    procedure Initialize; override;
    destructor Destroy; override;
  end;

implementation

uses ComServ;

procedure TSQLite.Initialize;
begin
  inherited;
  FConnection:=TSQLConnection.Create(nil);
  FConnection.DriverName:='Sqlite';
  FSQLQuery:=TSQLQuery.Create(nil);
  FSQLQuery.SQLConnection:=FConnection;
  FTransaction:=nil;
end;

function TSQLite.InTransaction: Integer;
begin
  result:= integer( FConnection.InTransaction );
end;

procedure TSQLite.BeginTransaction;
begin
  FTransaction:= FConnection.BeginTransaction;
end;

procedure TSQLite.CommitTransaction;
begin
  FConnection.CommitFreeAndNil(FTransaction);
end;

procedure TSQLite.RollbackTransaction;
begin
  FConnection.RollbackFreeAndNil(FTransaction);
end;

procedure TSQLite.QueryAdd(const Value: WideString);
begin
  FSQLQuery.SQL.Add(Value);
end;

procedure TSQLite.QueryClear;
begin
  FSQLQuery.SQL.Clear;
end;

function TSQLite.Connect: Integer;
begin
  FConnection.Open;
  result:= Connected();
end;

function TSQLite.Connected: Integer;
begin
  result:= integer( FConnection.Connected );
end;

procedure TSQLite.Disconnect;
begin
  if FConnection.Connected then
    FConnection.Close;
end;

function TSQLite.TableExists(const Index: WideString): Integer;
var
  list: TStringList;
begin
  list:=TStringList.Create;
  try
    FConnection.GetTableNames(list);
    if list.IndexOf(Index)>=0 then
      result:= 1
    else
      result:= 0
  except
    list.Free;
    raise;
  end;
  list.Free;
end;

function TSQLite.ExecuteSQL(const SQL: WideString): Integer;
begin
  QueryClear;
  QueryAdd(SQL);
  result:=ExecuteQuery;
end;

function TSQLite.ExecuteQuery: Integer;
begin
  result:= FSQLQuery.ExecSQL;
end;

procedure TSQLite.OpenQuery;
begin
  FSQLQuery.Open;
end;

procedure TSQLite.OpenSQL(const SQL: WideString);
begin
  QueryClear;
  QueryAdd(SQL);
  OpenQuery;
end;

function TSQLite.FieldName(Index: Integer): WideString;
begin
  result:= FSQLQuery.Fields[Index].FullName;
end;

function TSQLite.FieldsCount: Integer;
begin
  result:= FSQLQuery.Fields.Count;
end;

function TSQLite.ValueByName(const Index: WideString): OleVariant;
begin
  result:= FSQLQuery[Index];
end;

function TSQLite.ValueByIndex(Index: Integer): OleVariant;
begin
  result:= FSQLQuery.Fields[Index].Value;
end;

function TSQLite.Bof: Integer;
begin
  result:= integer( FSQLQuery.Bof );
end;

function TSQLite.Eof: Integer;
begin
  result:= integer( FSQLQuery.Eof );
end;

function TSQLite.RecordCount: Integer;
begin
  result:= FSQLQuery.RecordCount;
end;

function TSQLite.GetRecNo: Integer;
begin
  result:= FSQLQuery.RecNo;
end;

procedure TSQLite.SetRecNo(Index: Integer);
begin
  FSQLQuery.RecNo:= Index;
end;

function TSQLite.Next: Integer;
begin
  if Eof = 1 then
    result:= 0
  else begin
    FSQLQuery.Next;
    result:= 1;
  end;
end;

procedure TSQLite.First;
begin
  FSQLQuery.First;
end;

procedure TSQLite.Last;
begin
  FSQLQuery.Last;
end;

procedure TSQLite.Database(const DatabaseName: WideString; FailIfMissing: Integer);
begin
  if FConnection.Connected then
    FConnection.Close;

  FConnection.Params.Values['DataBase']:=DatabaseName;

  if FailIfMissing=1 then
    FConnection.Params.Values['FailIfMissing']:='True'
  else
    FConnection.Params.Values['FailIfMissing']:='False';

  FConnection.Params.Values['ColumnMetaDataSupported']:='False';

  Connect;
end;

destructor TSQLite.Destroy;
begin
  FSQLQuery.Free;
  if FConnection.InTransaction then begin
    FConnection.RollbackFreeAndNil(FTransaction);
  end;
  FConnection.Free;
  inherited;
end;

function TSQLite.RecCnt(Ina: Integer): Integer;
begin

end;

initialization
  TAutoObjectFactory.Create(ComServer, TSQLite, Class_SQLite,
    ciMultiInstance, tmApartment);
end.
